package drds.server.config.model;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Random;
import java.util.Set;

/**
 * 逻辑数据库,DRDS容器定义数据库表以及其他信息
 * 
 * @author 曹正辉<330937205@qq.com>
 * 
 */
public class Schema {
	private final String name;
	private final Random random = new Random();

	private final Map<String, Table> tableMap;
	private final Set<String> metaDataNodes;
	private final Set<String> allDataNodes;
	/**
	 * when a select sql has no limit condition ,and default max limit to
	 * prevent memory problem when return a large result set
	 */
	private final int defaultMaxLimit;
	private final boolean checkSQLSchema;
	/**
	 * key is join relation ,A.ID=B.PARENT_ID value is Root Table ,if a->b*->c*
	 * ,then A is root table
	 */
	private final Map<String, Table> joinSqlWithTableMap = new HashMap<String, Table>();
	private final String[] allDataNodeStringArray;

	public Schema(String name, String dataNode, Map<String, Table> tableMap, int defaultMaxLimit, boolean checkSQLschema) {
		this.name = name;
		this.checkSQLSchema = checkSQLschema;
		this.tableMap = tableMap;
		this.defaultMaxLimit = defaultMaxLimit;
		buildJoinMap();
		if (tableMap == null || tableMap.isEmpty()) {
			throw new RuntimeException(name + " in noSharding mode schema must have default dataNode ");
		}
		this.metaDataNodes = buildMetaDataNodes();
		this.allDataNodes = buildAllDataNodes();
		// this.metaDataNodes = buildAllDataNodes();
		if (this.allDataNodes != null && !this.allDataNodes.isEmpty()) {
			String[] dnArr = new String[this.allDataNodes.size()];
			dnArr = this.allDataNodes.toArray(dnArr);
			this.allDataNodeStringArray = dnArr;
		} else {
			this.allDataNodeStringArray = null;
		}
	}

	public boolean isCheckSQLSchema() {
		return checkSQLSchema;
	}

	public int getDefaultMaxLimit() {
		return defaultMaxLimit;
	}

	private void buildJoinMap() {

		if (tableMap == null || tableMap.isEmpty()) {
			return;
		}
		for (Table table : tableMap.values()) {
			if (table.isChildTable()) {
				Table rootParentTable = table.getRootParentTable();

				String childTableWithParentTableJoinSql = table.getName() + '.' + table.getJoinKeyColumnName() + '=' + table.getParentTable().getName() + '.' + table.getParentTableJoinedKeyColumnName();
				String parenTabletWithChildTableJoinSql = table.getParentTable().getName() + '.' + table.getParentTableJoinedKeyColumnName() + '=' + table.getName() + '.' + table.getJoinKeyColumnName();
				joinSqlWithTableMap.put(childTableWithParentTableJoinSql, rootParentTable);
				joinSqlWithTableMap.put(parenTabletWithChildTableJoinSql, rootParentTable);
			}

		}

	}

	public Map<String, Table> getJoinSqlAndTableMap() {
		return joinSqlWithTableMap;
	}

	public String getName() {
		return name;
	}

	public Map<String, Table> getTableMap() {
		return tableMap;
	}

	public Set<String> getMetaDataNodes() {
		return metaDataNodes;
	}

	public Set<String> getAllDataNodes() {
		return allDataNodes;
	}

	public String getRandomDataNode() {
		if (this.allDataNodeStringArray == null) {
			return null;
		}
		int index = Math.abs(random.nextInt(Integer.MAX_VALUE)) % allDataNodeStringArray.length;
		return this.allDataNodeStringArray[index];
	}

	/**
	 * 取得含有不同Meta信息的数据节点,比如表和表结构。
	 */
	private Set<String> buildMetaDataNodes() {
		Set<String> set = new HashSet<String>();

		for (Table table : tableMap.values()) {
			set.add(table.getDataNodeList().get(0));
		}

		return set;
	}

	/**
	 * 取得该schema的所有数据节点
	 */
	private Set<String> buildAllDataNodes() {
		Set<String> set = new HashSet<String>();

		for (Table table : tableMap.values()) {
			set.addAll(table.getDataNodeList());
		}
		return set;
	}

}